package cn.swing.main.srv.cv.model;

import cn.swing.main.srv.cv.utils.TennisKalmanFilter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import lombok.Data;

/**
 * 轨迹
 */
@Data
public class Trajectory {

    private int id;

    private int startFrameNumber;

    private int endFrameNumber;

    private List<TennisPoint> points = new ArrayList<>();

    int missedFrames = 0;

    private TennisKalmanFilter filter;

    private static final double MIN_SHAPE_SIMILARITY = 0.7;

    public Trajectory(List<TennisPoint> points) {
        this.points = points;
        this.startFrameNumber = points.get(0).getFrameNumber();
        this.endFrameNumber = points.get(points.size() - 1).getFrameNumber();
    }

    public Trajectory(TennisPoint p, int id) {
        this.id = id;
        this.startFrameNumber = p.getFrameNumber();
        this.endFrameNumber = p.getFrameNumber();
        this.points.add(p);
        p.setTrajectoryId(id + "");
        // 初始化卡尔曼滤波器
        filter = new TennisKalmanFilter(p);
    }

    public void add(TennisPoint point) {
        point.setTrajectoryId(id + "");
        this.points.add(point);
        calculateVelocity();
    }

    // 计算速度
    private void calculateVelocity() {
        if (points.size() < 2) {
            return;
        }

        TennisPoint prev = points.get(points.size() - 2);
        TennisPoint curr = points.get(points.size() - 1);

        int frameDiff = curr.getFrameNumber() - prev.getFrameNumber();
        if (frameDiff == 0) {
            return;
        }

        curr.vx = (curr.getX() - prev.getX()) / frameDiff;
        curr.vy = (curr.getY() - prev.getY()) / frameDiff;
    }

    public TennisPoint last() {
        return this.points.get(points.size() - 1);
    }

    public TennisPoint first() {
        return this.points.get(0);
    }

    public void merge(Trajectory other) {
        // 改轨迹ID
        other.points.forEach(p -> p.setTrajectoryId(this.id + ""));
        this.points.addAll(other.points);
        this.endFrameNumber = Math.max(this.endFrameNumber, other.endFrameNumber);
    }

    public List<TennisPoint> last5() {
        return this.points.subList(Math.max(0, this.points.size() - 5), this.points.size());
    }

    public List<TennisPoint> first5() {
        return this.points.subList(0, Math.min(5, this.points.size()));
    }

    // 获取当前轨迹，最后N个非重叠点（用于重合轨迹匹配）
    public List<TennisPoint> getLastNonOverlapPoints(Trajectory other, int n) {
        int overlapStart = Math.max(this.startFrameNumber, other.startFrameNumber);
        return this.points.stream()
                .filter(p -> p.frameNumber < overlapStart)
                // 按帧号倒序排序
                .sorted((a, b) -> b.frameNumber - a.frameNumber)
                .limit(n)
                .collect(Collectors.toList());
    }

    // 获取当前轨迹，前N个非重叠点（用于重合轨迹匹配）
    public List<TennisPoint> getFirstNonOverlapPoints(Trajectory other, int n) {
        int overlapEnd = Math.min(this.endFrameNumber, other.endFrameNumber);
        return this.points.stream()
                .filter(p -> p.frameNumber > overlapEnd)
                // 按帧号正序排序
                .sorted(Comparator.comparingInt(a -> a.frameNumber))
                .limit(n)
                .collect(Collectors.toList());
    }

}
